#ifndef SEU_DICT_H
#define SEU_DICT_H
#include"include.h"

/* A dictionary is a collection of key-value pairs ("associative array") where
 * values can be associated and looked up by an arbitrary key.
 *
 * This particular implementation uses a binary tree and a key comparison
 * function for fast lookups and storage via the key in the key-value pair.
 */


typedef struct dict_node_t {
   struct dict_node_t *left;
   struct dict_node_t *right;
   struct dict_node_t *parent;
   void *key;
   void *val;
} dict_node_t;

typedef struct dict_t {
   int size;
   unsigned char *hash; //Optional field 
   int cur;
   dict_node_t *root;
   int(*compare)(const void *, const void *);
   sem_t lock;
} dict_t;

typedef struct dict_key_val_t
{
   void *key;
   void *val;
} dict_key_val_t;

/* newDict - Returns a pointer to a malloced and properly constructed
 * dict_t.
 * params:
 *    compare - A comparison function used to compare keys in the dict_t, used
 *              for sorting for fast lookups. The function should return a
 *              negative number if left arg is less than right, 0 if they are
 *              equal, or positive number if left is less than right.
 * returns - A pointer to the new dict_t
 */
dict_t *newDict(int (*compare)(const void *, const void *));

/* dictClear - Removes all elements from a dict_t.
 * params:
 *    dict - The dictionary to clear.
 */
void dictClear(dict_t *dict);

/* dictClear - Removes all elements from a dict_t, freeing memory used by
 * keys and values as well.
 * params:
 *    dict - The dictionary to clear.
 */
void dictClearKeysVals(dict_t *dict);

/* dictPut - Places a key-value pairing into a dictionary.
 * params:
 *    dict - The dictionary within which to place the key-value pair.
 *    key  - The key with which a value is being associated.
 *    val  - The value that is being associated with the key.
 * returns - The value overwritten, if any. NULL if nothing was overwritten.
 */
void *dictPut(dict_t *dict, const void *key, const void *val);

/* dictGet - Returns the value in a dict_t associated with a particular key.
 * params:
 *    dict - The dictionary in which to look up the value associated with a key
 *    key  - The key by which to look up an associated value.
 * returns - The value associated with a particular key, NULL if no value is
 *           associated.
 */
void *dictGet(dict_t *dict, void *key);

/* dictIsEmpty - Returns whether or not there are any key-value pairs in a
 *               dict.
 * params:
 *    dict - The dictionary to check for key-value pairs.
 * returns - 1 if there are any pairs in the dict, 0 otherwise.
 */
int  dictIsEmpty(dict_t *dict);

/* dictRemove - Removes the key-value pair in a dict associated with a
 *              particular key.
 * params:
 *    dict - The dictionary to remove a key-value pair from.
 *    key  - The key associated with the key-value pair to remove.
 */
void dictRemove(dict_t *dict, void *key);

/* dictContainsKey - Returns whether or not a dict contains a key-value pair
 *                   for a particular key.
 * params:
 *    dict - The dictionary to check for a particular key.
 *    key  - The key to check to see if the dict contains a key-value pair for.
 * returns - 1 if the dict contains a pair for the key, 0 otherwise.
 */
int  dictContainsKey(dict_t *dict, void *key);

/* dictSize - Returns the number of key-value pairs contained in a particular
 *            dictionary.
 * params - the dictionary to check the number of pairs within.
 * returns - The number of pairs the dict contains.
 */
int  dictSize(dict_t *dict);

void dictLock(dict_t *dict);
void dictRelease(dict_t *dict);

/* dictTraversal - Returns a list of key-value pairs contained in a particular
 *                 dict.
 * params:
 *    dict - The dictionary to acquire all key-value pairs from.
 * returns - A list_t containing a dict_key_val_t for every key-value pair
 *           within the given dict.
 */
list_t *dictTraversal(dict_t *dict);


int integerCompare(const unsigned int *x, const unsigned int *y); //This is included because so the dict can
                                  //more easily be used as a sorta sparse array

#endif
